#include <iomanip>
#include "world.h"
#include "filesystem/be_filesystem.h"

World::World()
{
	settings = Settings::Instance();

	server = settings->getCVarPtr("server");
	client = settings->getCVarPtr("client");
	headless = settings->getCVarPtr("headless");

	// SERVER setup
	if ( *server )
		m_netServer.reset(new Netserver(settings->getCVar("port")));

	else if ( *client )
	{
		m_netClient.reset(new Netclient());
		m_netClient->connectToServer( settings->getCVarS("host"), settings->getCVar("port") );
	}
	
	m_sc_server.reset( new ScServer() );

	if ( !*headless )
	{
		// provide the local player if not headless
		m_sc_server->addLocalPlayer();
		m_sc_client.reset( new ScClient() );
	}

	// load cars
		ScCarDefLoader carDefLoader;
		BeFile befileCar;
		if ( BeFilesystem::Instance()->load(befileCar, "cars/miura_SV2/car.xml") )
			carDefLoader.load( ScCarDefManager::instance(), &befileCar );

	cout << ":: world setup" << endl;

}

void World::draw()
{
	m_sc_client->draw();
}

void World::process( float timeDelta )
{
	if ( !*client )
	{
	// NETWORK NEW CONNECTIONS
		if ( *server == 1 )
		{
			boost::shared_ptr<nClient> networkclient(m_netServer->getNewConnections( Timer::Instance()->sdl_now ));
			if ( networkclient != 0 )
				m_sc_server->addRemotePlayer( networkclient );
		}

	// SERVER: FETCH MESSAGES FROM CLIENTS
		for ( unsigned int i=0; i < m_sc_server->m_players.size(); i++ )
		{
			boost::shared_ptr<Player> p = m_sc_server->m_players[i];

			// REMOTE PLAYER
			if ( !p->isLocal() )
			{
				m_netServer->checkIncomingMessages( p->getNetworkclient(), &p->m_messages_in );

				if ( p->getNetworkclient()->toclose )
				{
					if ( p->isApproved() )
					{
						stringstream pldisc;
						pldisc << "pd "  << p->getId() << ";";
						m_sc_server->newMessageAllClients( pldisc.str() );
					}
					m_sc_server->m_players.erase( m_sc_server->m_players.begin()+i );
					--i;
				}
			}

			// LOCAL PLAYER
			else
			{
				p->m_messages_in = m_sc_client->m_messages_out;
				m_sc_client->m_messages_out.clear();
			}
		}

		m_sc_server->process( timeDelta );

	// SERVER: SEND MESSAGES TO CLIENTS
		for ( unsigned int i=0; i < m_sc_server->m_players.size(); i++ )
		{
			boost::shared_ptr<Player> p = m_sc_server->m_players[i];
			
			// REMOTE PLAYER
			if ( !p->isLocal() && p->isApproved() )
			{
				string msg;
				for ( unsigned int i=0; i < p->m_messages_out.size(); i++ )
					msg.append(p->m_messages_out[i]);
				p->m_messages_out.clear();

				m_netServer->sendMessage( p->getNetworkclient(), msg );
			}

			// LOCAL PLAYER
			else if ( p->isLocal() )
			{
				m_sc_client->m_messages_in = p->m_messages_out;
				p->m_messages_out.clear();
			}
		}

		if ( !*headless )
		{
			m_sc_client->process( timeDelta );
		}

	}
	
	// I AM A REMOTE CLIENT
	else
	{
		// RECIEVE MESSAGES
			m_netClient->checkIncomingMessages(&m_sc_client->m_messages_in);

			if ( m_netClient->toclose )
			{
				cerr << "remote server connection lost" << endl;
				exit(0);
			}

		if ( !*headless )
		{
			m_sc_client->process( timeDelta );
		}

		// SEND MESSAGES
			if ( m_sc_client->m_messages_out.size() > 0 )
			{
				string msg;
				for ( unsigned int i=0; i < m_sc_client->m_messages_out.size(); i++ )
					msg.append(m_sc_client->m_messages_out[i]);
				m_netClient->sendMessage(msg);
				m_sc_client->m_messages_out.clear();
			}
	}
}

World::~World()
{
	cerr << "exiting world" << endl;
}
